package cc.inq.db.tools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.firefly.db.util.DBInfo;
import org.firefly.db.util.DBName;

public class LoginComp extends Observable implements IWin {
	Shell shell;
	Display display;
	boolean flag = false; // 是否成功连接
	java.util.List<DBLinkInfo> dbLinks = null;
	Combo dbType;
	Text ip;
	Text port;
	Text dbName;
	Text usr;
	Text pwd;
	/**
	 * Create the composite.
	 * 
	 * @param shell
	 * @param style
	 */
	public LoginComp(Observer obServer) {
		this.addObserver(obServer);
		loadDBLinkInfos();
		boolean hasLinks = dbLinks != null && dbLinks.size() >0;
		display = new Display();
		shell = new Shell(display, SWT.CLOSE | SWT.MIN);
		shell.setText(Const.WIN_TITLE);
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = hasLinks ? 4 :3;
		gridLayout.marginTop = gridLayout.marginRight = gridLayout.marginBottom = gridLayout.marginLeft = 20;
		shell.setLayout(gridLayout);
		
		if (hasLinks) {
			makeLinkHistory();
		}

		dbType = addSelect("数据库", new String[] { Const.DB_MSSQL, Const.DB_MYSQL, Const.DB_ORACLE },
				Const.DB_MSSQL, 300, 3);
		ip = addInput("IP", "127.0.0.1", 200, 2);
		port = addInput(null, "1433", 50, 1); // 端口
		dbName = addInput("数据库名", null, 300, 3);
		usr = addInput("账号", null, 300, 3);
		pwd = addInput("密码", null, 300, 3);
		final LoginComp that = this;
		addBtn("连接", 100, 50, 3, new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				try {
					String url = makeURL(dbType.getText(), ip.getText(), port.getText(), dbName.getText());
					regDirver(dbType.getText());
					Connection srcConn = java.sql.DriverManager.getConnection(url, usr.getText(), pwd.getText());
					DBInfo srcInfo = new DBInfo(srcConn, null, getDBName(dbType.getText()));
					srcInfo.setUrl(url);
					writeDBInfo(new DBLinkInfo(dbType.getText(), dbName.getText(), ip.getText(), port.getText(), usr.getText(), pwd.getText()));
					that.setChanged(); // 注意：只有在setChange()被调用后，notifyObservers()才会去调用update()，否则什么都不干。
					that.notifyObservers(srcInfo);
					flag = true;
					that.deleteObservers();
				} catch (SQLException e) {
					WinUtil.showMsg(shell, SWT.OK | SWT.ICON_WARNING, "数据库连接失败", e.getMessage());
				}
			}

		});
	}

	public boolean isLogin() {
		return this.flag;
	}

	public void open() {
		shell.setSize(400, 200);
		shell.pack();
		shell.open();
		WinUtil.center(display, shell);
		while (!isLogin() && !shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	public void close() {
		this.shell.dispose();
		display.dispose();
	}

	public DBName getDBName(String dbName) {
		return Const.DB_MYSQL.equals(dbName) ? DBName.Mysql
				: Const.DB_MSSQL.equals(dbName) ? DBName.SqlServer2005
						: Const.DB_ORACLE.equals(dbName) ? DBName.Oracle : null;
	}

	private void loadDBLinkInfos() {
		dbLinks = new ArrayList();
		File f = loadConfigFile();
		BufferedReader fr = null;
		try {
			fr = new BufferedReader(new FileReader(f));
			Pattern p = Pattern.compile("^(.+?)\\s+(.+?)\\s+(.+?)\\s+(.+?)\\s+(.+?)\\s+(.+)$");
			String str = null;
			while ((str = fr.readLine()) != null) {
				Matcher m = p.matcher(str.trim());
				if(m.find()) {
					dbLinks.add(new DBLinkInfo(m.group(1), m.group(2), m.group(3), m.group(4), m.group(5), m.group(6)));
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fr != null) {
				try {
					fr.close();
				} catch (IOException e) {
				}
			}
		}
	}

	/**
	 * 写入新连接
	 * @author firefly
	 * @scene 2019年3月1日
	 * @param newLinkInfo
	 */
	private void writeDBInfo(DBLinkInfo newLinkInfo) {
		boolean exists = false;
		for (DBLinkInfo linkInfo : dbLinks) {
			if (linkInfo.getLable().equals(newLinkInfo.getLable())) {
				exists = true;
				// 已存在不需要新增
				break;
			}
		}
		if (!exists) {		
			BufferedWriter bw = null;
			try {
				File f = loadConfigFile();
				bw = new BufferedWriter(new FileWriter(f));
				bw.write(newLinkInfo.toString());
				bw.newLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				if (bw != null) {
					try {
						bw.close();
					} catch (IOException e) {
					}
				}
			}
		}
	}
	
	private File loadConfigFile() {
		try {
			File jarFile = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI());
	//		String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getFile();
	//		int firstIndex = path.lastIndexOf(System.getProperty("path.separator")) + 1;
	//		int lastIndex = path.lastIndexOf(File.separator) + 1;
	//		System.out.println("path:"+path);
	//		System.out.println("firstIndex:"+firstIndex);
	//		System.out.println("lastIndex:"+lastIndex);
	//		path = path.substring(firstIndex, lastIndex);
			File d = jarFile.isDirectory() ? jarFile : jarFile.getParentFile();
			if (d.exists() && d.isDirectory()) {
				File f = new File(d, Const.CONFIG);
				return f;
			}
		} catch (URISyntaxException e) {
//			System.out.println("不能获取app.conf文件");
		}
		return null;
	}

	/**
	 * 生成数据库url
	 * 
	 * @author firefly
	 * @scene 2019年2月27日
	 * @param dbType
	 * @param ip
	 * @param port
	 * @param dbName
	 * @param usr
	 * @param pwd
	 * @return
	 */
	protected String makeURL(String dbType, String ip, String port, String dbName) {
		if (Const.DB_MSSQL.equals(dbType)) {
			return String.format("jdbc:jtds:sqlserver://%s:%s/%s", new String[] { ip, port, dbName });
		} else if (Const.DB_MYSQL.equals(dbType)) {
			return String.format("jdbc:mysql://%s:%s/%s?useUnicode=true&characterEncoding=utf-8&autoReconnect=true",
					new String[] { ip, port, dbName });
		} else if (Const.DB_ORACLE.equals(dbType)) {
			return String.format("dbc:oracle:thin:@%s:%s:orcl", new String[] { ip, port });
		} else {
			return null;
		}
	}

	protected void regDirver(String dbType) {
		try {
			if (Const.DB_MSSQL.equals(dbType)) {
				Class.forName("net.sourceforge.jtds.jdbc.Driver");
			} else if (Const.DB_MYSQL.equals(dbType)) {
				Class.forName("com.mysql.jdbc.Driver");
			} else if (Const.DB_ORACLE.equals(dbType)) {
				Class.forName("oracle.jdbc.driver.OracleDriver");
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 生成历史列表
	 * @author firefly
	 * @scene 2019年3月1日
	 */
	public void makeLinkHistory() {
		final List categories = new List(this.shell, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
		String[] ls = new String[dbLinks.size()];
		for (int i = 0; i < dbLinks.size(); i++) {
			ls[i] = dbLinks.get(i).getLable();
		}
		categories.setItems(ls);
		GridData cgridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
		cgridData.verticalSpan = 6;
		int listHeight = categories.getItemHeight() * 12;
		Rectangle trim = categories.computeTrim(0, 0, 0, listHeight);
		cgridData.heightHint = trim.height;
		categories.setLayoutData(cgridData);
		categories.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				DBLinkInfo linkInfo = dbLinks.get(categories.getSelectionIndex());
//				for (DBLinkInfo linkInfo : dbLinks) {
//					if (linkInfo.getLable().equals() {
						dbType.setText(linkInfo.getType());
						dbName.setText(linkInfo.getDbName());
						ip.setText(linkInfo.getIp());
						port.setText(linkInfo.getPort());
						usr.setText(linkInfo.getUsr());
						pwd.setText(linkInfo.getPwd());
//						return;
//					}
//				}
			}
		});
	}

	/**
	 * 生成文本框
	 * 
	 * @author firefly
	 * @scene 2019年2月27日
	 * @param label
	 *            标签
	 * @param defVal
	 *            默认值
	 * @param width
	 *            宽度
	 * @param hIndent
	 *            横向占位
	 */
	public Text addInput(String label, String defVal, int width, int hIndent) {
		if (label != null) {
			new Label(this.shell, SWT.NONE).setText(label);
			hIndent--;
		}
		Text txt = new Text(this.shell, SWT.BORDER);
		if (defVal != null) {
			txt.setText(defVal);
		}
		// GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL, SWT.NONE, false, false, hIndent, 1);
		// gd.horizontalAlignment = GridData.FILL_HORIZONTAL;
		// gd.horizontalSpan = hIndent;
		// gd.horizontalIndent = hIndent;
		gd.widthHint = width;
		// gridData.heightHint = 80;
		txt.setLayoutData(gd);
		return txt;
	}

	/**
	 * 生成文本框
	 * 
	 * @author firefly
	 * @scene 2019年2月27日
	 * @param label
	 *            标签
	 * @param defVal
	 *            默认值
	 * @param width
	 *            宽度
	 * @param hIndent
	 *            横向占位
	 */
	public Combo addSelect(String label, String[] options, String defVal, int width, int hIndent) {
		if (label != null) {
			new Label(this.shell, SWT.NONE).setText(label);
			hIndent--;
		}
		Combo cb = new Combo(this.shell, SWT.DROP_DOWN | SWT.READ_ONLY);
		cb.setItems(options);
		if (defVal != null) {
			cb.setText(defVal);
		}
		GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		gd.horizontalAlignment = GridData.FILL_HORIZONTAL;
		gd.horizontalSpan = hIndent;
		gd.widthHint = width;
		cb.setLayoutData(gd);
		return cb;
	}

	/**
	 * 生成按钮
	 * 
	 * @author firefly
	 * @scene 2019年2月27日
	 * @param label
	 *            标签
	 * @param width
	 *            宽度
	 * @param hIndent
	 *            横向占位
	 */
	public void addBtn(String label, int width, int height, int hIndent, SelectionAdapter click) {
		Button enter = new Button(this.shell, SWT.PUSH);
		enter.setText(label);
		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
		gridData.horizontalSpan = hIndent;
		gridData.widthHint = width;
		gridData.heightHint = height;
		enter.setLayoutData(gridData);
		enter.addSelectionListener(click);
	}

}